package server;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

public class MyClassLoader extends ClassLoader {
    //指定路径
    private String path;

    public MyClassLoader() {
    }

    /**
     *
     * @param absolutePath 指定路径下加载class,若加载异常则用默认类加载器
     * @param servletClass
     * @return
     */
    public HttpServlet getClassLoadServlet(String absolutePath,String servletClass) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        HttpServlet httpServlet = null;
        File webfile = new File(absolutePath);
        String[] split = servletClass.split("\\.");
        StringBuilder servletClassPath = new StringBuilder();
        for (int i = 0; i < split.length; i++) {
            if(i+1 == split.length ){
                servletClassPath.append("\\").append(split[i]).append(".class");
            }else{
                servletClassPath.append("\\").append(split[i]);
            }
        }
        path = webfile.getParent()+servletClassPath;
        try {
            httpServlet = (HttpServlet)findClass(servletClass).getDeclaredConstructor().newInstance();

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("自定义类加载器加载类异常, 使用默认的类加载器加载");
            httpServlet = (HttpServlet) Class.forName(servletClass).getDeclaredConstructor().newInstance();
        }

        return httpServlet;
    }

    /**
     * 重写findClass方法
     *
     * @param name 是我们这个类的全路径
     * @return
     */
    @Override
    protected Class<?> findClass(String name) {
        Class<?> log = null;
        // 获取该class文件字节码数组
        byte[] classData = getData();

        if (classData != null) {
            // 将class的字节码数组转换成Class类的实例
            log = defineClass(name, classData, 0, classData.length);
        }
        return log;
    }

    /**
     * 将class文件转化为字节码数组
     *
     * @return
     */
    private byte[] getData() {

        File file = new File(path);
        if (file.exists()) {
            FileInputStream in = null;
            ByteArrayOutputStream out = null;
            try {
                in = new FileInputStream(file);
                out = new ByteArrayOutputStream();

                byte[] buffer = new byte[1024];
                int size;
                while ((size = in.read(buffer)) != -1) {
                    out.write(buffer, 0, size);
                }

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException e) {

                    e.printStackTrace();
                }
            }
            return out.toByteArray();
        } else {
            return null;
        }
    }
}